package com.service.service;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;

/**
 * oid:就是一些参数的代名词
 * mib树：就是信息树，可以通过 oid去信息树里面查找设备的信息
 * 通过snmp获取设备信息
 */
public class SnmpServiceImpl {

    //其实下面的参数就是 SnmpConstants中定义的常量

    //获取系统基本信息
    static final String oid1 =".1.3.6.1.2.1.1.1.0"; //等价于 =》 new OID(new int[]{1, 3, 6, 1, 2,1,1,1,0});
    //网络接口的数目
    static final String oid2 =".1.3.6.1.2.1.2.1.0";
    //网络接口类型
    static final String oid3 =".1.3.6.1.2.1.2.2.1.3";

    //cpu相关的
    //用户cpu百分比
    static final String oid4 =".1.3.6.1.4.1.2021.11.9.0";
    //系统cpu百分比
    static final String oid5 =".1.3.6.1.4.1.2021.11.10.0";
    //空闲cpu百分比
    static final String oid6 =".1.3.6.1.4.1.2021.11.11.0";

    //磁盘相关的
    //内存大小
    static final String oid7 ="1.3.6.1.2.1.25.2.2.0";
    //存储设备编号
    static final String oid8 ="1.3.6.1.2.1.25.2.3.1";
    //存储设备类型
    static final String oid9 ="1.3.6.1.2.1.25.2.3.1.2";



    static final String oidFive =".1.3.6.1.2.1.2.2.1.8";
    static final String oidSix =".1.3.6.1.2.1.2.2.1.2";

    //oid还以写成集合的形式
    //static final int[]0ID5 = {1,3,6,1,2,1,1,2};与第一个一样
    //设备名称
    static final String sysName =".1.3.6.1.2.1.1.5.0";
    //获取系统描述
    static final String sysDesc =".1.3.6.1.2.1.1.1.0";
    //网络接口数量
    static final String ifNumber =".1.3.6.1.2.1.2.1.0";
    //网络接口速度
    static final String ssCpuIdle =".1.3.6.1.4.1.2021.11.11.0";
    //内存大小
    static final String hrMemerySize =".1.3.6.1.2.1.25.2.2.0";

    public static void   doSnmp() {

        //设置传输协议
        TransportMapping transport = null ;

        try {
            transport = new DefaultUdpTransportMapping();
            transport.listen();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //PDU就是要传输的数据
        PDU pdu = new PDU();
        pdu.add(new VariableBinding(new OID(oid1)));
        pdu.add(new VariableBinding(new OID(oid2)));
        pdu.add(new VariableBinding(new OID(oid3)));
        pdu.add(new VariableBinding(new OID(oid4)));
        pdu.add(new VariableBinding(new OID(oid5)));
        pdu.add(new VariableBinding(new OID(oid6)));
        pdu.add(new VariableBinding(new OID(oid7)));
        pdu.add(new VariableBinding(new OID(oid8)));
        pdu.add(new VariableBinding(new OID(oid9)));
        //从服务器得到的oid
        pdu.add(new VariableBinding(new OID(sysName)));
        pdu.add(new VariableBinding(new OID(sysDesc)));
        pdu.add(new VariableBinding(new OID(ifNumber)));
        pdu.add(new VariableBinding(new OID(ssCpuIdle)));
        pdu.add(new VariableBinding(new OID(hrMemerySize)));

        //这里有几种可以选择的值
        /**
         * PDU.GET  这是一个GET请求，用于从SNMP代理获取一个或多个指定的MIB变量的值。当您需要读取网络设备上的特定信息时，会使用GET请求。
         * PDU.SET  这是一个SET请求，用于向SNMP代理设置一个或多个指定的MIB变量的值。当您需要修改网络设备的配置时，会使用SET请求。
         * PDU.GETNEXT 这是一个GETNEXT请求，用于检索MIB树中给定节点的下一个节点的信息。GETNEXT请求通常用于执行SNMP walk操作，即遍历整个MIB树并检索所有可用的MIB变量。
         * PDU.TRAP  发送一个trap请求
         */
        pdu.setType(PDU.GET);


        //snmp初始化
        Snmp snmp = new Snmp(transport);

        //发送的目的地 => 请求的地址
        CommunityTarget target = new CommunityTarget();
        Address localAddress = GenericAddress.parse("udp:47.100.122.116/161");
        System.out.println(pdu); //GETNEXT[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.1.0 = Null; 1.3.6.1.2.1.2.2.1.2.2 = Null]]
        OctetString oct = new OctetString("public");
        target.setCommunity(oct);
        target.setVersion(SnmpConstants.version2c);
        target.setAddress(localAddress);
        target.setRetries(2);
        target.setTimeout(2*1000);

        //发送报文
        try {
            ResponseEvent responseEvent = snmp.send(pdu, target);
            PDU response = responseEvent.getResponse();
            if (response !=null){
                System.out.println("request.size = "+pdu.size());
                System.out.println("response.size = " + response.size());
                VariableBinding vb1 = response.get(0);
                VariableBinding vb2 = response.get(1);
                VariableBinding vb3 = response.get(2);
                VariableBinding vb4 = response.get(3);
                VariableBinding vb5 = response.get(4);
                VariableBinding vb6 = response.get(5);
                VariableBinding vb7 = response.get(6);
                VariableBinding vb8 = response.get(7);
                VariableBinding vb9 = response.get(8);
                //
                VariableBinding sysName = response.get(9);
                VariableBinding sysDesc = response.get(10);
                VariableBinding ifNumber = response.get(11);
                VariableBinding ssCpuIdle = response.get(12);
                VariableBinding hrMemerySize = response.get(13);


                System.out.println("//获取系统基本信息："+vb1);
                System.out.println("//网络接口的数目："+vb2);
                System.out.println("//网络接口类型："+vb3);
                System.out.println("//用户cpu百分比："+vb4);
                System.out.println("//系统cpu百分比："+vb5);
                System.out.println("//空闲cpu百分比："+vb6);
                System.out.println("//内存大小："+vb7);
                System.out.println("//存储设备编号："+vb8);
                System.out.println("//存储设备类型："+vb9);
                System.out.println("----------------------");
                System.out.println("//设备名称："+sysName);
                System.out.println("//设备描述："+sysDesc);
                System.out.println("//接口数量："+ifNumber);
                System.out.println("//cpu空闲数量："+ssCpuIdle);
                System.out.println("//磁盘大小："+hrMemerySize);

                transport.close();
            }else {
                System.err.println("响应结果为空！！！");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                transport.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SnmpServiceImpl.doSnmp();
    }

}
